"""
Python数据容器对比与选择指南

Python提供了四种主要的数据容器：
1. 列表(List)：可变、有序、允许重复元素
2. 元组(Tuple)：不可变、有序、允许重复元素
3. 字典(Dict)：可变、(Python 3.7+有序)、键值对映射、键不可重复
4. 集合(Set)：可变、无序、不允许重复元素

本示例将通过代码和示例帮助你理解这些容器的特性，并指导如何在实际开发中选择合适的容器。
"""

import timeit
import sys

print("="*60)
print("Python数据容器对比与选择指南")
print("="*60)

# =============== 1. 容器特性对比 ===============

print("\n1. 容器特性对比")
print("-"*40)

# 创建不同类型的容器示例
example_list = [1, 2, 3, 2, 4]
example_tuple = (1, 2, 3, 2, 4)
example_dict = {"a": 1, "b": 2, "c": 3, "d": 4}
example_set = {1, 2, 3, 2, 4}  # 注意2重复了，但集合中只会保留一个

print("示例数据:")
print(f"列表(List): {example_list}")
print(f"元组(Tuple): {example_tuple}")
print(f"字典(Dict): {example_dict}")
print(f"集合(Set): {example_set}")

# 1.1 可变性测试
print("\n1.1 可变性:")
print("列表(List): 可变 - 可以添加、删除和修改元素")
print("元组(Tuple): 不可变 - 创建后不能修改")
print("字典(Dict): 可变 - 可以添加、删除和修改键值对")
print("集合(Set): 可变 - 可以添加和删除元素")

print("\n可变性演示:")
# 列表可变性
example_list.append(5)
example_list[0] = 10
print(f"修改后的列表: {example_list}")

# 元组不可变性
try:
    example_tuple[0] = 10  # 这会引发错误
except TypeError as e:
    print(f"尝试修改元组: {e}")

# 字典可变性
example_dict["e"] = 5
example_dict["a"] = 10
print(f"修改后的字典: {example_dict}")

# 集合可变性
example_set.add(5)
example_set.remove(1)
print(f"修改后的集合: {example_set}")

# 1.2 有序性测试
print("\n1.2 有序性:")
print("列表(List): 有序 - 元素保持插入顺序")
print("元组(Tuple): 有序 - 元素保持插入顺序")
print("字典(Dict): Python 3.7+有序 - 键值对保持插入顺序")
print("集合(Set): 无序 - 元素顺序不固定")

# 1.3 索引访问
print("\n1.3 索引/键访问:")
print(f"列表索引访问: example_list[2] = {example_list[2]}")
print(f"元组索引访问: example_tuple[2] = {example_tuple[2]}")
print(f"字典键访问: example_dict['c'] = {example_dict['c']}")
try:
    print(f"集合不支持索引访问: {example_set[2]}")
except TypeError as e:
    print(f"集合索引访问错误: {e}")

# 1.4 重复元素
print("\n1.4 重复元素:")
print(f"列表允许重复: [1, 2, 2, 3] -> {[1, 2, 2, 3]}")
print(f"元组允许重复: (1, 2, 2, 3) -> {(1, 2, 2, 3)}")
print(f"字典不允许键重复: 后面的会覆盖前面的 -> {{'a':1, 'a':2}} -> {dict({'a':1, 'a':2})}")  # noqa: F601
print(f"集合不允许重复: {{1, 2, 2, 3}} -> {set({1, 2, 2, 3})}") # 显示{1, 2, 3}

# 1.5 内存占用测试
print("\n1.5 内存占用对比:")
data = list(range(1000))
list_mem = sys.getsizeof(data)
tuple_mem = sys.getsizeof(tuple(data))
dict_mem = sys.getsizeof({i: i for i in range(1000)})
set_mem = sys.getsizeof(set(data))

print(f"列表(1000个元素): {list_mem} 字节")
print(f"元组(1000个元素): {tuple_mem} 字节")
print(f"字典(1000个键值对): {dict_mem} 字节")
print(f"集合(1000个元素): {set_mem} 字节")
print(f"元组比列表节省: {(list_mem - tuple_mem) / list_mem:.2%}")


# =============== 2. 性能测试 ===============

print("\n" + "="*60)
print("2. 性能测试")
print("-"*40)

# 2.1 创建速度测试
print("\n2.1 创建速度对比:")
list_create_time = timeit.timeit('x = [i for i in range(10000)]', number=1000)
tuple_create_time = timeit.timeit('x = tuple(i for i in range(10000))', number=1000)
dict_create_time = timeit.timeit('x = {i: i for i in range(10000)}', number=1000)
set_create_time = timeit.timeit('x = {i for i in range(10000)}', number=1000)

print(f"列表创建耗时: {list_create_time:.4f} 秒")
print(f"元组创建耗时: {tuple_create_time:.4f} 秒")
print(f"字典创建耗时: {dict_create_time:.4f} 秒")
print(f"集合创建耗时: {set_create_time:.4f} 秒")

# 2.2 查找性能测试
print("\n2.2 查找性能对比:")
setup_code = """
list_data = list(range(10000))
tuple_data = tuple(range(10000))
dict_data = {i: i for i in range(10000)}
set_data = set(range(10000))
"""

list_lookup = timeit.timeit('9999 in list_data', setup=setup_code, number=10000)
tuple_lookup = timeit.timeit('9999 in tuple_data', setup=setup_code, number=10000)
dict_lookup = timeit.timeit('9999 in dict_data', setup=setup_code, number=10000)
set_lookup = timeit.timeit('9999 in set_data', setup=setup_code, number=10000)

print(f"列表查找耗时: {list_lookup:.4f} 秒")
print(f"元组查找耗时: {tuple_lookup:.4f} 秒")
print(f"字典查找耗时: {dict_lookup:.4f} 秒")
print(f"集合查找耗时: {set_lookup:.4f} 秒")
print(f"集合比列表查找快: {list_lookup/set_lookup:.1f}倍")
print(f"字典比列表查找快: {list_lookup/dict_lookup:.1f}倍")


# =============== 3. 应用场景选择指南 ===============

print("\n" + "="*60)
print("3. 应用场景选择指南")
print("-"*40)

print("""
选择合适的容器类型，应考虑以下因素:
1. 数据是否需要修改？(可变性)
2. 是否需要保持元素顺序？(有序性)
3. 是否需要通过键快速查找？(索引/键访问)
4. 元素是否允许重复？(唯一性)
5. 是否需要进行集合运算？(交集/并集等)
""")

# 3.1 各容器的适用场景
print("\n3.1 各容器的适用场景:")
print("""
【列表(List)】适用场景:
- 需要存储可变的、有序的元素集合
- 数据需要经常增加、删除或修改
- 需要保持插入顺序
- 允许重复元素
- 需要通过索引位置访问元素

【元组(Tuple)】适用场景:
- 需要存储不可变的、有序的元素集合
- 数据一旦创建就不会改变
- 作为字典的键或集合的元素
- 多个值的返回(函数返回多个值实际上是返回一个元组)
- 配置参数、不可变数据的传递

【字典(Dict)】适用场景:
- 需要通过键快速查找值
- 需要存储键值对映射关系
- 需要频繁查询或更新数据
- 键必须是唯一且不可变的
- 需要根据某个属性或ID查找对象

【集合(Set)】适用场景:
- 需要存储不重复元素
- 主要用于判断元素是否存在
- 需要执行集合运算(交集、并集、差集)
- 需要高效去重
- 不关心元素顺序
""")

# =============== 4. 实际应用案例 ===============

print("\n" + "="*60)
print("4. 实际应用案例")
print("-"*40)

# 4.1 使用列表处理模型返回的批量预测结果
predictions_list = []
print("4.1 使用列表处理模型预测结果:")
print("# 模拟接收模型批量预测结果")
predictions_list.append({"id": 1, "prediction": "正面", "confidence": 0.95})
predictions_list.append({"id": 2, "prediction": "负面", "confidence": 0.87})
predictions_list.append({"id": 3, "prediction": "中性", "confidence": 0.76})
print(f"模型预测结果列表: {predictions_list}")
print("优势: 可以动态添加新预测，保持顺序，支持排序和过滤")

# 4.2 使用元组存储不可变配置参数
print("\n4.2 使用元组存储模型超参数:")
model_params = (
    ("model_name", "gpt-3.5-turbo"),
    ("temperature", 0.7),
    ("max_tokens", 500),
    ("top_p", 0.95)
)
print(f"模型参数元组: {model_params}")
print("优势: 参数配置不可篡改，确保训练和推理过程一致性")

# 4.3 使用字典存储API配置和参数映射
print("\n4.3 使用字典存储API配置:")
api_config = {
    "api_key": "sk-abcdef123456",
    "base_url": "https://api.openai.com/v1",
    "headers": {
        "Content-Type": "application/json",
        "Authorization": "Bearer sk-abcdef123456"
    },
    "params": {
        "temperature": 0.7,
        "max_tokens": 500,
        "stream": True
    }
}
print(f"API配置字典: {api_config}")
print("优势: 可以通过键名快速查找和更新配置项，层级结构清晰")

# 4.4 使用集合处理用户输入去重
print("\n4.4 使用集合处理关键词去重与集合运算:")
user_interests1 = {"AI", "机器学习", "Python", "数据科学", "深度学习"}
user_interests2 = {"Python", "Web开发", "数据科学", "JavaScript", "云计算"}

common_interests = user_interests1 & user_interests2  # 交集运算
all_interests = user_interests1 | user_interests2     # 并集运算
unique_to_user1 = user_interests1 - user_interests2   # 差集运算

print(f"用户1兴趣: {user_interests1}")
print(f"用户2兴趣: {user_interests2}")
print(f"共同兴趣: {common_interests}")
print(f"所有兴趣: {all_interests}")
print(f"仅用户1的兴趣: {unique_to_user1}")
print("优势: 快速去重、高效率集合运算，O(1)时间复杂度的成员检查")

# 4.5 多选题答案判定案例
print("\n4.5 使用集合处理多选题答案判定:")

def check_multi_choice_answer(correct_answer, student_answer):
    """检查多选题答案是否正确"""
    # 将答案字符串转换为集合，忽略顺序
    correct_set = set(correct_answer)
    student_set = set(student_answer)
    
    # 检查两个集合是否相等
    return correct_set == student_set

# 测试几组答案
test_cases = [
    {"correct": "ABC", "student": "CBA", "should_pass": True},
    {"correct": "AD", "student": "ADE", "should_pass": False},
    {"correct": "BC", "student": "B", "should_pass": False}
]

for i, case in enumerate(test_cases):
    result = check_multi_choice_answer(case["correct"], case["student"])
    status = "正确" if result else "错误"
    expected = "正确" if case["should_pass"] else "错误"
    
    print(f"测试{i+1}: 标准答案={case['correct']}, 学生答案={case['student']}")
    print(f"判定结果: {status} (期望: {expected})")
    print(f"解释: 标准答案集合={set(case['correct'])}, 学生答案集合={set(case['student'])}\n")


# =============== 5. 综合应用：AI助手开发场景 ===============

print("\n" + "="*60)
print("5. 综合应用：AI助手开发场景")
print("-"*40)

print("""
在AI助手开发中，我们需要同时使用多种数据容器，发挥各自优势:
""")

# 元组存储模型参数（不可变配置）
model_params = (
    ("model", "gpt-3.5-turbo"),
    ("temperature", 0.7),
    ("max_tokens", 500)
)

# 列表存储对话历史（有序、可追加）
chat_history = [
    {"role": "user", "content": "你能帮我制定一个学习Python的计划吗？"},
    {"role": "assistant", "content": "当然可以！以下是学习Python的分步计划..."},
    {"role": "user", "content": "谢谢，我想先学习数据容器"}
]

# 字典存储API配置（键值映射、快速查找）
api_config = {
    "api_key": "sk-abcdef123456",
    "base_url": "https://api.openai.com/v1",
    "timeout": 30,
    "retries": 3
}

# 集合存储唯一关键词（去重、集合运算）
keywords = set()
for message in chat_history:
    if message["role"] == "user":
        # 模拟从用户消息中提取关键词
        extracted = {"Python", "学习", "计划", "数据容器"}
        keywords.update(extracted)

print("AI助手开发中的数据容器应用:")
print(f"1. 模型参数元组(不可变配置): {model_params}")
print(f"2. 对话历史列表(有序、可追加): {chat_history}")
print(f"3. API配置字典(键值映射): {api_config}")
print(f"4. 关键词集合(去重): {keywords}")

# =============== 6. 数据容器选择决策流程 ===============

print("\n" + "="*60)
print("6. 数据容器选择决策流程")
print("-"*40)

print("""
如何选择合适的数据容器？请遵循以下决策流程:

1. 是否需要键值对映射关系？
   → 是：使用字典(Dict)
   → 否：继续下一步

2. 数据是否需要保持不可变？
   → 是：使用元组(Tuple)
   → 否：继续下一步

3. 是否需要元素唯一且支持集合运算？
   → 是：使用集合(Set)
   → 否：使用列表(List)

补充考虑因素:
- 查找频率高：优先考虑字典或集合（O(1)时间复杂度）
- 数据量大且内存敏感：优先考虑元组（内存占用更小）
- 需要频繁修改：优先考虑列表（动态增删改）
- 需要保持插入顺序：使用列表或元组（Python 3.7+字典也保持顺序）
""")

print("\n" + "="*60)
print("总结：各数据容器最显著的特点")
print("-"*40)
print("列表(List): 可变、有序、支持索引访问、允许重复元素")
print("元组(Tuple): 不可变、有序、支持索引访问、允许重复元素")
print("字典(Dict): 可变、键值对映射、键不可重复、高效查找")
print("集合(Set): 可变、无序、元素唯一、支持集合运算")
print("\n选择正确的数据容器可以让你的Python程序更高效、更易维护！")
print("="*60)
